//
//  DUPopMonthView.swift
//  SimpleCal
//
//  Created by 杜晓祥 on 2021/11/4.
//

import Cocoa

@IBDesignable
class DUPopMonthView: NSView {
    
    private let weekValue = ["日", "一", "二", "三", "四", "五", "六"]
    private var dayGroup = ButtonGroup<DUCalDayButton>(check: true)
    var id:String = ""// self().className
    private var year:Int = 0
    private var month:Int = 0
    private var startIndex: Int = 0
    private var endIndex: Int = 0
    private var monthLabel:DULabel!
    private var allowsStatus:Bool = false
    private var bottomLine: DUHorizontalLine!
    private var topLine: DUHorizontalLine!
    
    var selectedList = [BaseViewButton.StateValue: [DUCalDayButton]]()
    
    var onChange: ((_ sender: DateEntity, _ state: BaseViewButton.StateValue) -> Void)?
    var titleType:DayTitle = .month
    
    var borderWidth:CGFloat = 1
    var borderColor:CGColor = CGColor(gray: 0.7, alpha: 0.7)
    
    
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        initialize()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        initialize()
    }
    
    override func layout() {
        self.layer?.borderWidth = self.borderWidth
        self.layer?.borderColor = self.borderColor
        monthLabel.setFrameSize(NSSize(width: self.frame.width, height: 30))
        if year != 0 && month != 0 {
            setDate(year: year, month: month)
        }
        topLine.frame = NSMakeRect(0, 200, self.frame.width, 1)
        bottomLine.frame = NSMakeRect(0, 1, self.frame.width, 1)
    }
    
    private func initialize() {
        titleType = .month
        monthLabel = DULabel()
        monthLabel.frame = NSMakeRect(0, 195, self.frame.width, 30)
        monthLabel.font = NSFont.systemFont(ofSize: 18)
        addSubview(monthLabel)
        topLine = DUHorizontalLine(frame: NSMakeRect(0, 200, self.frame.width, 1))
        addSubview(topLine)
        bottomLine = DUHorizontalLine(frame: NSMakeRect(0, 1,self.frame.width, 1))
        bottomLine.isHidden = true
        addSubview(bottomLine)
        
        dayGroup.btnChange = dayGroupChnage
        var x:CGFloat = 0
        for w in weekValue {
            let l = DULabel()
            l.frame = NSMakeRect(x, 180, 30, 15)
            l.font = NSFont.systemFont(ofSize: 10)
            l.stringValue = w
            addSubview(l)
            x += 30
        }
        for i in (0...5) {
            for j in (0...6) {
                let x = CGFloat(j*30)
                let y = CGFloat((5-i)*30)
                let day = DUCalDayButton(frame: NSMakeRect(x, y, 30, 30))
                day.setNil()
                day.dayType = .general
                day.notMonth = true
                day.isEnable = enableAll
                day.allowsState = true
                dayGroup.addSubview(button: day)
                self.addSubview(day)
            }
        }
    }
    
    var topLineIsHidden:Bool = false {
        didSet {
            self.topLine.isHidden = topLineIsHidden
        }
    }
    
    var bottomLineIsHidden:Bool = true {
        didSet {
            self.bottomLine.isHidden = bottomLineIsHidden
        }
    }
    
    func cleanSelected () {
        selectedList.removeAll()
        dayGroup.clean()
    }
    
    private func dayGroupChnage(button: DUCalDayButton) {
        if onChange != nil {
            if !selectedList.isEmpty {
                cleanSelected()
            }
            onChange!(button.date!, button.state)
            return
        }
        deleteSelected(button: button)
        if button.state == .off {
            return
        }
        var b = selectedList[button.state]
        if b == nil {
            b = [DUCalDayButton]()
        }
        b!.append(button)
        selectedList.updateValue(b!, forKey: button.state)
    }
    
    private func deleteSelected (button: DUCalDayButton) {
        for e in BaseViewButton.StateValue.allCases {
            if var n = selectedList[e] {
                if let i = n.firstIndex(of: button) {
                    n.remove(at: i)
                    selectedList.updateValue(n, forKey: e)
                }
            }
            
        }
    }
    
    func setDate(year: Int, month: Int) {
        setDate(year: year, month: month, day: 1)
    }
    
    func setDate(year: Int, month: Int, day: Int) {
        setDate(year: year, month: month, day: day, selecteds: [])
    }
    
    func setDate(year:Int, month:Int, day: Int, selecteds: [DateEntity]) {
        dayGroup.clean()
        self.y = year
        self.m = month
        monthLabel.stringValue = title()
        let date = CalendarUtil.getDateEntity(year: year, month: month, day: 1)
        
        let s = date.solar
        var dayIndex = s.week - 1
        startIndex = dayIndex
        var i = 0
        while i < dayIndex {
            let d = dayGroup.getSubview(index: i)
            d.dayType = .general
            d.setNil()
            d.isEnable = false
            d.notMonth = true
            i+=1
        }
        i = 1
        while i <= CalendarUtil.getMonthDays(year: year, month: month) {
            let d = dayGroup.getSubview(index: dayIndex)
            let d1 = CalendarUtil.getDateEntity(year: year, month: month, day: i)
            d.setDate(date: d1)
            if let j = selecteds.firstIndex(where: {$0.equal(date: d1)}) {
                d.state = getDayTypeToState(type: selecteds[j].dayType)
            }
            d.isEnable = enableAll
            dayIndex += 1
            i += 1
        }
        endIndex = dayIndex
        while dayIndex < dayGroup.count() {
            let d = dayGroup.getSubview(index: dayIndex)
            d.dayType = .general
            d.setNil()
            d.isEnable = false
            d.notMonth = true
            dayIndex += 1
        }
    }
    
    private func getDayTypeToState(type: DateEntity.DayType) -> BaseViewButton.StateValue {
        switch type {
            case .currentDay:
                return .off
            case .festvial:
                return .on
            case .general:
                return .off
            case .holiday:
                return .holiday
            case .week:
                return .off
            case .work:
                return .work
        }
    }
    
    @IBInspectable var y:Int = 0 {
        didSet {
            self.year = y
        }
    }
    
    @IBInspectable var m:Int = 0 {
        didSet {
            self.month = m
        }
    }
    
    var enableAll:Bool = true {
        didSet {
            dayGroup.isEnable = enableAll
//            var i = startIndex
//            while i < endIndex {
////                days[i].isEnabled = enableAll
//                dayGroup.isEnable = enableAll
//                i+=1
//            }
        }
    }
    
    private func title() -> String {
        switch titleType {
            case .year:
                return "\(self.year)年"
            case .month:
                return "\(self.month)月"
            case .own:
                return "\(self.year)年\(self.month)月"
        }
    }
    
    func setFixedConstraint(width:CGFloat, height:CGFloat) {
        let fixedWidth = NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: width)
        let fixedHeight = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: height)
        self.addConstraints([fixedWidth, fixedHeight])
    }
    
    enum  DayTitle {
        case year
        case month
        case own
    }
    
}

fileprivate extension DUCalDayButton.CalDayStyle {
    private static var BLACK_COLOR = CGColor(red: 0, green: 0, blue: 0, alpha: 1)
    private static var RED_COLOR = CGColor(red: 0.96, green: 0.2, blue: 0.2, alpha: 1)

    static var defaultStyle: DUCalDayButton.CalDayStyle {
        get {
            var d = DUCalDayButton.CalDayStyle()
            d.solarForegroundColor = BLACK_COLOR
            d.lunarForegroundColor = BLACK_COLOR
            d.holidayIsHidden = true
            d.maskIsHidden = true
            d.backgroundColor = NSColor.white.cgColor
            d.alphaValue = 1
            return d
        }
    }
    
    static var currentStyle: DUCalDayButton.CalDayStyle {
        get {
            var d = DUCalDayButton.CalDayStyle()
            d.solarForegroundColor = BLACK_COLOR
            d.lunarForegroundColor = BLACK_COLOR
            d.holidayIsHidden = true
            d.maskIsHidden = true
            d.backgroundColor = nil
            d.alphaValue = 1
            return d
        }
    }
    
    /**
     周末样式
     */
    static var weekStyle:DUCalDayButton.CalDayStyle {
        get {
            var d = DUCalDayButton.CalDayStyle()
            d.solarForegroundColor = RED_COLOR//BLACK_COLOR
            d.lunarForegroundColor = BLACK_COLOR
            d.holidayIsHidden = true
            d.maskIsHidden = true
            d.backgroundColor = nil
            d.alphaValue = 1
            return d
        }
    }
    
    /**
     节假日样式
     */
    static var holidayStyle:DUCalDayButton.CalDayStyle {
        get {
            var d = DUCalDayButton.CalDayStyle()
            d.solarForegroundColor = RED_COLOR//BLACK_COLOR
            d.lunarForegroundColor = BLACK_COLOR
            d.holidayIsHidden = false
            d.holidayForegroundColor = CGColor(red: 0.96, green: 0.19, blue: 0.19, alpha: 1)
            d.maskIsHidden = true
            d.backgroundColor = CGColor(red: 0.98, green: 0.89, blue: 0.89, alpha: 0.7)
            d.alphaValue = 1
            return d
        }
    }

    /**
     加班倒休日样式
     */
    static var workStyle:DUCalDayButton.CalDayStyle {
        get {
            var d = DUCalDayButton.CalDayStyle()
            d.solarForegroundColor = BLACK_COLOR
            d.lunarForegroundColor = BLACK_COLOR
            d.holidayIsHidden = false
            d.holidayForegroundColor = CGColor(red: 0.36, green: 0.4, blue: 0.45, alpha: 1)
            d.maskIsHidden = true
            d.backgroundColor = CGColor(red: 0.8, green: 0.8, blue: 0.8, alpha: 0.7)
            d.alphaValue = 1
            return d
        }
    }
}
 

